package cn.ts.android.attendance.lock;


import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 */
public class MapWithLock<K, V> extends ObjWithLock<Map<K, V>> {
    private static final long serialVersionUID = -652862323697152866L;

    /**
     */
    public MapWithLock(Map<K, V> map) {
        super(map);
    }

    /**
     * @param lock
     */
    public MapWithLock(Map<K, V> map, ReentrantReadWriteLock lock) {
        super(map, lock);
    }

    /**
     *
     * @param key
     * @param value
     */
    public V put(K key, V value) {
        ReentrantReadWriteLock.WriteLock writeLock = this.getLock().writeLock();
        writeLock.lock();
        try {
            Map<K, V> map = this.getObj();
            return map.put(key, value);
        } catch (Throwable e) {
            System.out.println(e.getMessage());
        } finally {
            writeLock.unlock();
        }
        return null;
    }

    /**
     *
     * @param key
     * @param value
     */
    public V putIfAbsent(K key, V value) {
        ReentrantReadWriteLock.WriteLock writeLock = this.getLock().writeLock();
        writeLock.lock();
        try {
            Map<K, V> map = this.getObj();
            V oldValue = map.putIfAbsent(key, value);
            if (oldValue == null) {
                return value;
            } else {
                return oldValue;
            }

        } catch (Throwable e) {
            System.out.println(e.getMessage());
        } finally {
            writeLock.unlock();
        }
        return null;
    }

    /**
     *
     * @param otherMap
     */
    public void putAll(Map<K, V> otherMap) {
        if (otherMap == null || otherMap.isEmpty()) {
            return;
        }

        ReentrantReadWriteLock.WriteLock writeLock = this.getLock().writeLock();
        writeLock.lock();
        try {
            Map<K, V> map = this.getObj();
            map.putAll(otherMap);
        } catch (Throwable e) {
            System.out.println(e.getMessage());
        } finally {
            writeLock.unlock();
        }
    }

    /**
     *
     * @param key
     * @return
     */
    public V remove(K key) {
        ReentrantReadWriteLock.WriteLock writeLock = this.getLock().writeLock();
        writeLock.lock();
        try {
            Map<K, V> map = this.getObj();
            return map.remove(key);
        } catch (Throwable e) {
            System.out.println(e.getMessage());
        } finally {
            writeLock.unlock();
        }
        return null;
    }

    /**
     * clear
     */
    public void clear() {
        ReentrantReadWriteLock.WriteLock writeLock = this.getLock().writeLock();
        writeLock.lock();
        try {
            Map<K, V> map = this.getObj();
            map.clear();
        } catch (Throwable e) {
            System.out.println(e.getMessage());
        } finally {
            writeLock.unlock();
        }
    }

    /**
     *
     * @param key
     * @return
     */
    public V get(K key) {
        ReentrantReadWriteLock.ReadLock readLock = this.getLock().readLock();
        readLock.lock();
        try {
            Map<K, V> map = this.getObj();
            return map.get(key);
        } catch (Throwable e) {
            System.out.println(e.getMessage());
        } finally {
            readLock.unlock();
        }
        return null;
    }

    /**
     *
     * @return
     */
    public int size() {
        ReentrantReadWriteLock.ReadLock readLock = this.getLock().readLock();
        readLock.lock();
        try {
            Map<K, V> map = this.getObj();
            return map.size();
        } finally {
            readLock.unlock();
        }
    }

}